package com.atguigu.vip.spring.framework.context.support;


import com.atguigu.vip.spring.framework.beans.BeanDefinition;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/***
 * 用来对配置文件进行查找，读取，解析。。。。
 */
public class BeanDefinitionReader {
    private Properties config = new Properties();
    private List<String> registryBeanClasses = new ArrayList<>();
    //在配置文件中，用来获取自动扫描的包名的key..
    private final String SCAN_PACKAGE = "scanPackage";
    /**
     * 获得配置信息
     */
    public BeanDefinitionReader(String... locations) {
        //在spring中是通过Reader去查找和定位的。这里简单起见，直接用Properties去read
        InputStream is  = this.getClass().getClassLoader().
                getResourceAsStream(locations[0].replace("*:","")); //这里应该是数组，简便起见用了[0]
        try {
            config.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null != is){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        doScanner(config.getProperty(SCAN_PACKAGE));
    }

    //配置信息都保存在这里
    public List<String> loadBeanDefinitions(){
        return this.registryBeanClasses;
    }

    //这是BeanDefinitionReader一个重要的方法
    //传入一个className，就返回一个BeanDefinition，BeanDefinition是我们自己包装的
    //只是为了对配置信息进行一个包装。
    public BeanDefinition registerBean(String className){
        if(this.registryBeanClasses.contains(className)){
            BeanDefinition beanDefinition = new BeanDefinition();
            beanDefinition.setBeanClassName(className);
            beanDefinition.setFactoryBeanName(lowerFirstCase(className.substring(className.lastIndexOf(".") + 1)));
            return beanDefinition;
        }
        return null;
    }

    //递归扫描所有的相关联的class，并保存到一个List中
    private void doScanner(String packageName) {
        //怎么加载呢，现在springMVC又流行的是注解的方式,所以根据注解来加载
        //把所有要加载的类全部放到一个容器中
        URL url = this.getClass().getClassLoader().getResource(
                "/" + packageName.replaceAll("\\.","/"));
        File classDir = new File(url.getFile());
        for (File file : classDir.listFiles()) {
            if(file.isDirectory()){
                doScanner(packageName + "."+ file.getName() );
            }else{
                //所有类名全部放到className中
                registryBeanClasses.add(packageName + "." + file.getName().replaceAll(".class",""));
            }
        }
    }

    /**
     * 在外面拿到这个配置信息
     */
    public Properties getConfig(){
        return this.config;
    }

    private String lowerFirstCase(String source){
        char[] chars = source.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }

}
